﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Collections;
namespace Kwan.Data
{
    /// <summary>
    /// 数据库连接上下文
    /// </summary>
    class ConnectionContext : IConnectinContext
    {
        public ConnectionContext(string db, IDriver driver, ConnectionType type)
        {
            mDB = db;
            if (DBContext.CurrentHandler(db) == null)
            {
                DBContext.AddConnectionHandler(mDB, driver);
                mActiveConnection = true;
            }
            mHandler = DBContext.CurrentHandler(mDB);
            Type = type;
        }

        public int ExecuteNonQuery(Command cmd)
        {
            return mHandler.ExecuteNonQuery(cmd);
        }
        public IDataReader ExecuteReader(Command cmd)
        {
            return mHandler.ExecuteReader(cmd);
        }

        public object ExecuteScalar(Command cmd)
        {
            return mHandler.ExecuteScalar(cmd);

        }

        public DataSet ExecuteDataSet(Command cmd)
        {
            return mHandler.ExecuteDataSet(cmd);
        }

        private string mDB;
        private bool mActiveConnection = false;
        private bool mActiveTransaction = false;
        ConnectionHandler mHandler;

        #region IDisposable 成员

        public void Dispose()
        {
            if (mActiveTransaction)
                mHandler.Rollback();
            if (mActiveConnection)
            {
                mHandler.Dispose();
                DBContext.RemoveConnetionHandler(mDB);
            }
        }

        #endregion

        #region IDbTransaction 成员
        public void BeginTransaction()
        {
            if (mHandler.Transaction == null)
            {
                mHandler.BeginTransaction();
                mActiveTransaction = true;

            }
        }
        public void Commit()
        {
            if (mActiveTransaction)
            {
                mHandler.Commit();
            }
        }

        public IDbConnection Connection
        {
            get
            {
                return mHandler.Connection;
            }
        }

        public IsolationLevel IsolationLevel
        {
            get { return mHandler.IsolationLevel; }
        }



        #endregion

        #region IDbTransaction 成员


        public void Rollback()
        {
            if (mActiveTransaction)
            {
                mHandler.Rollback();
            };
        }

        #endregion

        #region IConnectinContext 成员


        public IList<T> List<T>(Command cmd, Region region) where T : IEntityState, new()
        {

            return (IList<T>)List(typeof(T), cmd, region);
        }

        public T Load<T>(Command cmd) where T : IEntityState, new()
        {

            return (T)Load(typeof(T), cmd);

        }

        #endregion

        #region IConnectinContext 成员


        public T ListFirst<T>(Command cmd) where T : IEntityState, new()
        {


            return (T)ListFirst(typeof(T), cmd);
        }

        #endregion

        #region IConnectinContext 成员


        public ConnectionType Type
        {
            get;
            set;
        }

        #endregion

        #region IConnectinContext 成员


        public IList List(Type type, Command cmd, Region region)
        {
            if (type.GetInterface("IEntityState") == null)
                throw new KwanDataException(string.Format(DataMsg.OBJECT_NOTIMPL_IENTITYSTATE, type));
            if (region == null)
                region = new Region { Start = 0, Size = 99999999 };

            IList items = null;
            System.Type itemstype = System.Type.GetType("System.Collections.Generic.List`1");
            itemstype = itemstype.MakeGenericType(type);
            items = (IList)Activator.CreateInstance(itemstype);
            IEntityState item = null;
            using (IDataReader reader = ExecuteReader(cmd))
            {
                int index = 0;
                while (reader.Read())
                {
                    if (index >= region.Start)
                    {
                        item = (IEntityState)Activator.CreateInstance(type);
                        item.ConnectionType = this.Type;
                        item.LoadData(reader);
                        items.Add(item);
                        if (items.Count == region.Size)
                        {
                            cmd.DbCommand.Cancel();
                            break;
                        }
                    }
                    index++;
                }
            }
            return items;
        }

        public object ListFirst(Type type, Command cmd)
        {
            IList items = List(type, cmd, null);
            if (items.Count > 0)
                return items[0];
            return null;
        }

        public object Load(Type type, Command cmd)
        {
            IList items = List(type, cmd, null);
            if (items.Count > 0)
                return items[0];
            return null;
        }

        #endregion
    }
}
